

/** INCLUDES *******************************************************/

#include "Compiler.h"
#include "GenericTypeDefs.h"
#include "HardwareProfile.h"
#include "usb_config.h"
#include "USB/usb_device.h"
#include "USB/usb.h"
#include "USB/usb_function_generic.h"
#include "chunk_buffer.h"

#include "user.h"
#include "types.h"


/** V A R I A B L E S ********************************************************/
#pragma udata

//BYTE counter;

#pragma udata USB_VARS
HOST_PACKET LogPacket;
HOST_PACKET CntrlPacket;
#pragma udata

USB_HANDLE USBGenericOutHandle = 0;
USB_HANDLE USBGenericInHandle = 0;

T0CON_T			gt0con	= 0x97;
T1CON_T			gt1con	= 0xff;
ADCON0_T		gadcon0	= 0x0;
ADCON1_T		gadcon1	= 0xe;
ADCON2_T		gadcon2 = 0x9d; // bit 7(right justified), 6 - undef,5..3 - asqusition time(011-6Tad), 2..0 - Conversiotion clock 101 - Fosc/16 
TMR0L_T			gtmr0l	= 0xff;
TMR0H_T			gtmr0h	= 0xfc;
TMR1L_T			gtmr1l	= 0x0;
TMR1H_T			gtmr1h	= 0x0;

ADC_MODE		gadcmode = PACKET;

// Timer0 - 1 second interval setup.
// Fosc/4 = 12MHz
// Use /256 prescalar, this brings counter freq down to 46,875 Hz
// Timer0 should = 65536 - 46875 = 18661 or 0x48E5
//#define TIMER0L_VAL         0xE5
//#define TIMER0H_VAL         0x48

/** P R I V A T E  P R O T O T Y P E S ***************************************/


void setStateBits(int value);
void setServiceBits(int value);

void Show_USB_State(void);
void ServiceRequests(void);

void handlePacket (const HOST_PACKET *in, HOST_PACKET *out);
void config_getdata (CONFIG_OPTIONS *pco);


/** D E C L A R A T I O N S **************************************************/
#pragma code
void UserInit(void)
{
    #if defined(__18CXX)
    /* Init Timer0 for data logging interval (every 1 second) */
    T0CON = 0x97;
    /* Timer0 is already enabled by default */
    #elif defined(__C30__)
    #endif

    TRISD = 0x00; /* configure all PORTD pins for output */
    PORTD = 0x00; /* default LED configuration is off */

	mInitButton1();
	//setupTimer();
	setupTimer (gtmr0h, gtmr0l);
	//TMR0H=gtmr0h;
	//TMR0L=gtmr0l;
	//TMR1H=gtmr1h;
	//TMR1L=gtmr1l;
	cntrlTimer(0x97);
	setupClock(gtmr1h, gtmr1l);
	clearTimerInterrupt();
	enableTimerInterrupt();
	selectADCChannel0();
	enableADC();
	setupADC1(gadcon1);
	setupADC2(gadcon2);
	setADCInterruptPrioHigh();
	clearADCInterrupt();
	enableADCInterrupt();
	enableGlobalInterrupt();


}//end UserInit


/******************************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is a place holder for other user routines.
 *                  It is a mixture of both USB and non-USB tasks.
 *
 * Note:            None
 *****************************************************************************/
void ProcessIO(void)
{

	Show_USB_State();

	// User Application USB tasks
	if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1))
//		CntrlPacket.id = ADC_QUERY;
//		LogPacket.id = ADC;
//		LogPacket.data.chunks.length = 2;
//		LogPacket.data.chunks.data[0].id = 1;
//		LogPacket.data.chunks.data[0].time = 2;
//		LogPacket.data.chunks.data[0].value = 3;
//		LogPacket.data.chunks.data[1].id = 4;
//		LogPacket.data.chunks.data[1].time = 5;
//		LogPacket.data.chunks.data[1].value = 6;
//		handlePacket(&CntrlPacket, &LogPacket);
		return;

    ServiceRequests();

}//end ProcessIO


/******************************************************************************
 * Function:        void ServiceRequests(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    USB traffic can be generated
 *
 * Overview:        This function takes in the commands from the PC application the
 *                  application and executes requested commands
 *
 * Note:            None
 *****************************************************************************/
void ServiceRequests(void)
{
    BYTE i;

    //Check to see if data has arrived
    if(!USBHandleBusy(USBGenericOutHandle))
    {
		if(!USBHandleBusy(USBGenericInHandle))
		{
			//chunk_buffer_getdata (&LogPacket.data);
			handlePacket (&CntrlPacket, &LogPacket);
			USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE *)&LogPacket,USBGEN_EP_SIZE
				/*LogPacket.data.chunks.length * sizeof(CHUNK) + sizeof(WORD)*/);
		}

        //Re-arm the OUT endpoint for the next packet
       USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&CntrlPacket,USBGEN_EP_SIZE);
    }//end if

}//end ServiceRequests

void config_getdata (CONFIG_OPTIONS *pco)
{
	pco->t0con	= gt0con;
	pco->tmr0h	= gtmr0h;
	pco->tmr0l	= gtmr0l;
	pco->adcon0	= gadcon0;
	pco->adcon1	= gadcon1;
	pco->adcon2 = gadcon2;
	pco->t1con	= gt1con;
	pco->tmr1l  = gtmr1l;
	pco->tmr1h	= gtmr1h;
}

void config_setdata (CONFIG_OPTIONS *pco)
{
	disableGlobalInterrupt();

	if (gt0con != pco->t0con) {
		gt0con = pco->t0con;
		cntrlTimer (gt0con);
	}

	if (gtmr0h != pco->tmr0h || gtmr0l != pco->tmr0l) {
		gtmr0h = pco->tmr0h;
		gtmr0l = pco->tmr0l;
		setupTimer (gtmr0h, gtmr0l);
	}

	if (gt1con != pco->t1con) {
		gt1con = pco->t1con;
		cntrlClock (gt1con);
	}

	if (gtmr1h != pco->tmr1h || gtmr1l != pco->tmr1l) {
		gtmr1h = pco->tmr1h;
		gtmr1l = pco->tmr1l;
		setupClock (gtmr1h, gtmr1l);
	}

	if (gadcon1 != pco->adcon1) {
		gadcon1 = pco->adcon1;
	}

	if (gadcon2 != pco->adcon2) {
		gadcon2 = pco->adcon2;
	}

	if (gadcon0 != pco->adcon0) {
		BYTE adcmode = pco->adcon0 >> 6 &0x3;
		if (adcmode != gadcmode) {
			gadcmode = adcmode;
			if (gadcmode == SINGLE) {
				disableADCInterrupt();
				PORTD = 0b00001101;
			}
			if (gadcmode == PACKET) {
				PORTD = 0b00001110;
				enableADCInterrupt();
			}
		}
		if (pco->adcon0 & 0x1 != gadcon0 & 0x1) {
			if (pco->adcon0 & 0x1)
				enableADC();
			else
				disableADC();
		}
		gadcon0 = pco->adcon0 & 0x3f;
	}
	enableGlobalInterrupt();
}

void setStateBits(int value)
  {
	if (button1 != 0)
		PORTD = value | (0b00011111 & LATD);
  }

void setServiceBits(int value)
  {
  //  PORTD = value | (0b00011111 & LATD);
  //    PORTD = value << 2; // | (0b11100000 & LATD);
  //	  PORTD = 0b0101;
  }

void handlePacket (const HOST_PACKET *inPacket, HOST_PACKET *outPacket)
{
	switch (inPacket->id)
	{
	case ADC_QUERY :
		PORTD = 0b00001000;
		if (gadcmode == PACKET) 
			chunk_buffer_getdata (&outPacket->data.chunks);
		else
			adc_getdata (inPacket->data.poll.pollId, &outPacket->data.adc);
		outPacket->id = ADC;
		break;
	case CONFIG_QUERY :
		PORTD = 0b00000100;
		config_getdata (&outPacket->data.coptions);
		outPacket->id = CONFIG;
		break;
	case CONFIG_CNTRL :
		PORTD = 0b00001100;
		config_setdata (&inPacket->data.coptions);
		config_getdata (&outPacket->data.coptions);
		outPacket->id = CONFIGCNTRL;
		break;
	default :
		PORTD = 0b00000010;
		break;
	}
}

void Show_USB_State(void)
  {
    static int configured = 1;

    if(USBSuspendControl == 1)
      {
        configured = 0;
        setStateBits(0b00000000);
        return;
      }

    switch (USBDeviceState)
      {
        case POWERED_STATE:
                configured = 0;
                setStateBits(0b10000000);
                break;
        case DETACHED_STATE:
                configured = 0;
                setStateBits(0b01000000);
                break;
        case ATTACHED_STATE:
                configured = 0;
                setStateBits(0b11000000);
                break;
        case DEFAULT_STATE:
                configured = 0;
                setStateBits(0b00100000);
                break;
        case ADDRESS_STATE:
                configured = 0;
                setStateBits(0b10100000);
                break;
        case CONFIGURED_STATE:
                if (configured) break;
                configured = 1;
                setStateBits(0b11100000);
                break;
      }
  }

void setupTimer (TMR0H_T th, TMR0L_T tl)
{
	TMR0H = th;
	TMR0L = tl;
}

void setupClock (TMR1H_T th, TMR1L_T tl)
{
	TMR1H = th;
	TMR1L = tl;
}

void setupADC1 (ADCON1_T adcon1)
{
	ADCON1 = adcon1;
}

void setupADC2 (ADCON2_T adcon2)
{
	ADCON2 = adcon2;
}


void adc_getdata (POLL_ID_T id, ADC_DATA *pd) 
{
	static BYTE pollId = 0;
	PORTD = 0b00000100;
	if (pollId != id) {
		pd->id = pollId;
		pd->value = 0;
		if (isADCstarted()) {
			//old conversion pending yet
			pd->state = WAIT;
			PORTD = 0b00000001;
			return;
		}
		//start ADC
		startADC();
		pd->id = id;
		pd->state = START;
		pollId = id;
		PORTD = 0b00000010;
		return;
	}
	PORTD = ADCON0;
	if (isADCstarted()) {
		pd->id = id;
		pd->state = WAIT;
		PORTD = 0b00000011;
		pd->value = 0;
		return;
	}
	if (isADCdone()) {
		pd->id = id;
		pd->state = DONE;
		pd->value = ADRES;
		PORTD = 0b00000000;
		return;
	}		
}



